package com.zbkj.crmeb.category.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.common.CommonResult;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.PageHelper;
import com.utils.CrmebUtil;
import com.zbkj.crmeb.category.dao.CategoryDao;
import com.zbkj.crmeb.category.model.Category;
import com.zbkj.crmeb.category.request.CategoryRequest;
import com.zbkj.crmeb.category.request.CategorySearchRequest;
import com.zbkj.crmeb.category.request.UpdateCateRatioRequest;
import com.zbkj.crmeb.category.service.CategoryMenuTypeService;
import com.zbkj.crmeb.category.service.CategoryService;
import com.zbkj.crmeb.category.vo.CategoryTreeVo;
import com.zbkj.crmeb.chant.model.CategoryMatch;
import com.zbkj.crmeb.chant.service.ICategoryMatchService;
import com.zbkj.crmeb.enums.IdentityTypeEnum;
import com.zbkj.crmeb.store.model.ChannelCategoryConfig;
import com.zbkj.crmeb.store.service.ChannelCategoryConfigService;
import com.zbkj.crmeb.system.service.SystemAdminService;

/**
* @author Mr.Zhang
* @Description CategoryServiceImpl 接口实现
* @since 2020-04-16
*/
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, Category> implements CategoryService {
    @Resource
    private CategoryDao dao;
    @Autowired
    private SystemAdminService systemAdminService;

    @Autowired
    ICategoryMatchService categoryMatchService;
    @Autowired
    private ChannelCategoryConfigService channelCategoryConfigService;

    @Resource
    private CategoryMenuTypeService categoryMenuTypeService;


    /**
     * 获取分类下子类的数量
     * @param request 请求参数
     * @param pageParamRequest 分页参数
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return List<Category>
     */
    @Override
    public List<Category> getList(CategorySearchRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<Category> categories = null;
        if(Objects.equals(request.getType(),1)){
            LambdaQueryWrapper<CategoryMatch> wrapper = Wrappers.<CategoryMatch>lambdaQuery().eq(null != request.getIsAdvice() && CollectionUtils.isEmpty(request.getIds()), CategoryMatch::getIsAdvice, request.getIsAdvice())
                    .eq(null != request.getPid(), CategoryMatch::getPid, request.getPid())
                    .eq(CategoryMatch::getType, request.getType())
                    .eq(null != request.getStatus(), CategoryMatch::getStatus, request.getStatus())
                    .eq(null != request.getName(), CategoryMatch::getName, request.getName())
                    .in(CollectionUtils.isNotEmpty(request.getIds()), CategoryMatch::getId, request.getIds())
                    .orderByDesc(CategoryMatch::getSort).orderByDesc(CategoryMatch::getId);
            List<CategoryMatch> list = categoryMatchService.list(wrapper);
            if(CollectionUtils.isNotEmpty(list)){
               categories = list.stream().map(e -> {
                    Category cate = new Category();
                    BeanUtils.copyProperties(e, cate,"type");
                    cate.setType(e.getType().getCode());
                    return cate;
                }).collect(Collectors.toList());
            }
        }else{
            LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            Category category = new Category();
            BeanUtils.copyProperties(request,category);
//        objectQueryWrapper.setEntity(category);
            if(null != category.getIsAdvice() && CollectionUtils.isEmpty(request.getIds())){
                lambdaQueryWrapper.eq(Category::getIsAdvice, category.getIsAdvice());
            }
            if(null != category.getPid()){
                lambdaQueryWrapper.eq(Category::getPid, category.getPid());
            }
            if(null != category.getType()){
                lambdaQueryWrapper.eq(Category::getType, category.getType());
            }
            if(null != category.getStatus()){
                lambdaQueryWrapper.eq(Category::getStatus, category.getStatus());
            }
            if(null != category.getName()){
                lambdaQueryWrapper.like(Category::getName, category.getName());
            }
            lambdaQueryWrapper.eq(null != request.getStatus(), Category::getStatus, request.getStatus());
            lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(request.getIds()), Category :: getId, request.getIds());
            lambdaQueryWrapper.orderByDesc(Category::getSort).orderByDesc(Category::getId);
            categories = dao.selectList(lambdaQueryWrapper);
        }
        return categories;
    }

    /**
     * 通过id集合获取列表
     * @param idList List<Integer> id集合
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return List<Category>
     */
    @Override
    public List<Category> getByIds(List<Integer> idList) {
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(Category::getId, idList);
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 通过id集合获取列表 id => name
     * @param cateIdList List<Integer> id集合
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return HashMap<Integer, String>
     */
    @Override
    public HashMap<Integer, String> getListInId(List<Integer> cateIdList) {
        HashMap<Integer, String> map = new HashMap<>();
        List<Category> list = getByIds(cateIdList);
        for (Category category : list){
            map.put(category.getId(), category.getName());
        }

        return map;
    }

    /**
     * 批量查询分类id是否合法
     * @param categoryIdList List<Integer> id集合
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public void checkCategoryIsExist(List<Integer> categoryIdList) {
        //查询分类id是否合法
        HashMap<Integer, String> categoryServiceListInId = getListInId(categoryIdList);
        if(categoryServiceListInId.size() != categoryIdList.size()){
            for (Integer categoryId: categoryIdList) {
                String categoryName = CrmebUtil.getStrValueByIndex(categoryServiceListInId, categoryId);

                if(categoryName.equals("")){
                    //如果取出的分类名称是空， 那么有问题
                    throw new CrmebException("ID是 " + categoryId + "的分类不存在，或者分类名称为空！");
                }
            }
        }
    }

    /**
     * 查询id和url是否存在
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return Boolean
     */
    @Override
    public Boolean checkAuth(List<Integer> pathIdList, String uri) {
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(Category::getId, pathIdList).eq(Category::getUrl, uri);
        List<Category> categoryList = dao.selectList(lambdaQueryWrapper);
        return categoryList.size() >= 1;
    }

    /**
     * 修改
     * @param request CategoryRequest
     * @param id Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return bool
     */
    @Override
    public boolean update(CategoryRequest request, Integer id) {
        try{
            //修改分类信息
            Category category = new Category();
            BeanUtils.copyProperties(request, category);
            category.setId(id);
            category.setPath(getPathByPId(category.getPid()));

            updateById(category);

            //如状态为关闭，那么所以子集的状态都关闭
            if(!request.getStatus()){
                updateStatusByPid(id, false);
            }else{
                //如是开启，则父类的状态为开启
                updatePidStatusById(id);
            }

            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 开启父级状态
     * @param id Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    private void updatePidStatusById(Integer id) {
        Category category = getById(id);
        List<Integer> categoryIdList = CrmebUtil.stringToArrayByRegex(category.getPath(), "/");
        categoryIdList.removeIf(i -> i.equals(0));
        ArrayList<Category> categoryArrayList = new ArrayList<>();
        if(categoryIdList.size() < 1){
            return;
        }
        for (Integer categoryId: categoryIdList) {
            Category categoryVo = new Category();
            categoryVo.setId(categoryId);
            categoryVo.setStatus(true);
            categoryArrayList.add(categoryVo);
        }
        updateBatchById(categoryArrayList);
    }

    /**
     * 获取分类下子类的数量
     * @param pid Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return bool
     */
    private int getChildCountByPid(Integer pid) {
        //查看是否有子类
        QueryWrapper<Category> objectQueryWrapper = new QueryWrapper<>();
//        objectQueryWrapper.eq("status", 1);
        objectQueryWrapper.like("path", "/"+pid+"/");
        return dao.selectCount(objectQueryWrapper);
    }

    /**
     * 修改分类以及子类的状态
     * @param pid Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return bool
     */
    private int updateStatusByPid(Integer pid, boolean status) {
        //查看是否有子类
        Category category = new Category();
        category.setStatus(status);

        QueryWrapper<Category> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.like("path", "/"+pid+"/");
        return dao.update(category, objectQueryWrapper);
    }

    @Override
    public String getPathByPId(Integer pid) {
        Category category = getById(pid);
        if(null != category){
            return category.getPath() + pid + "/";
        }
        return null;
    }

    /**
     * 带结构的无线级分类
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<CategoryTreeVo> getListTree(Integer type, Integer status, Integer merId) {
        return getTree(type, status, null, merId);
    }

    /**
     * 带权限的属性结构
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<CategoryTreeVo> getFrontListTree(Integer type, Integer status) {
        return getFrontTree(type, status, null);
    }

    /**
     * 带权限的属性结构
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<CategoryTreeVo> getListTree(Integer type, Integer status, List<Integer> categoryIdList) {
        return getTree(type, status, categoryIdList, null);
    }

    /**
     * 带结构的无线级分类
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    private List<CategoryTreeVo> getTree(Integer type, Integer status, List<Integer> categoryIdList, Integer merId) {
        //循环数据，把数据对象变成带list结构的vo
        List<CategoryTreeVo> treeList = new ArrayList<>();
        List<Category> allTree = null;
        if(1 == type){
            LambdaQueryWrapper<CategoryMatch> queryWrapper = Wrappers.<CategoryMatch>lambdaQuery().eq(CategoryMatch::getType, type)
                    .in(null != categoryIdList && categoryIdList.size() > 0, CategoryMatch::getId, categoryIdList)
                    .eq(status >= 0, CategoryMatch::getStatus, status)
                    .orderByDesc(CategoryMatch::getSort)
                    .orderByAsc(CategoryMatch::getId);
            List<CategoryMatch> list = categoryMatchService.list(queryWrapper);
            if(CollectionUtils.isEmpty(list)){
                return null;
            }
            allTree = list.stream().map(e->{
                Category category = new Category();
                BeanUtils.copyProperties(e,category);
                category.setType(e.getType().getCode());
                return category;
            }).collect(Collectors.toList());
        }else {
            LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Category::getType, type);
            if (Constants.CATEGORY_TYPE_ATTACHMENT == type) {
                lambdaQueryWrapper.eq(merId != null, Category::getMerId, merId);
            }

            if(null != categoryIdList && categoryIdList.size() > 0){
                lambdaQueryWrapper.in(Category::getId, categoryIdList);
            }

            if(status >= 0){
                lambdaQueryWrapper.eq(Category::getStatus, status);
            }
            lambdaQueryWrapper.orderByDesc(Category::getSort);
            lambdaQueryWrapper.orderByAsc(Category::getId);
            allTree = dao.selectList(lambdaQueryWrapper);
        }

        if(allTree == null){
            return null;
        }

        // 处理菜单身份类型
        boolean menuFlag = false;
        Map<Integer, Set<Integer>> identityTypeMap = new HashMap<>();
        if (Constants.CATEGORY_TYPE_MENU == type) {
            List<Integer> ids = allTree.stream().map(Category::getId).collect(Collectors.toList());
            identityTypeMap = categoryMenuTypeService.getMenuIdentityTypeMap(null, ids);
            menuFlag = true;
        }
        for (Category category: allTree) {
            CategoryTreeVo categoryTreeVo = new CategoryTreeVo();
            BeanUtils.copyProperties(category, categoryTreeVo);
            if (menuFlag) {
                categoryTreeVo.setIdentityTypes(identityTypeMap.get(category.getId()));
            }
            treeList.add(categoryTreeVo);
        }

        //返回
        Map<Integer, CategoryTreeVo> map = new HashMap<>();
        //ID 为 key 存储到map 中
        for (CategoryTreeVo categoryTreeVo1 : treeList) {
            map.put(categoryTreeVo1.getId(), categoryTreeVo1);
        }

        List<CategoryTreeVo> list = new ArrayList<>();
        for (CategoryTreeVo tree : treeList) {
            //子集ID返回对象，有则添加。
            CategoryTreeVo tree1 = map.get(tree.getPid());
            if(tree1 != null){
                tree1.getChild().add(tree);
            }else {
                list.add(tree);
            }
        }
        return list;
    }

    /**
     * 小程序 - 带结构的无线级分类
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    private List<CategoryTreeVo> getFrontTree(Integer type, Integer status, List<Integer> categoryIdList) {
        //循环数据，把数据对象变成带list结构的vo
        List<CategoryTreeVo> treeList = new ArrayList<>();
        List<Category> allTree;
        if(1 == type){
            LambdaQueryWrapper<CategoryMatch> wrapper = Wrappers.<CategoryMatch>lambdaQuery().eq(CategoryMatch::getType, type)
                    .in(null != categoryIdList && categoryIdList.size() > 0, CategoryMatch::getId, categoryIdList)
                    .eq(status >= 0, CategoryMatch::getStatus, status)
                    .orderByDesc(CategoryMatch::getSort)
                    .orderByAsc(CategoryMatch::getId);
            List<CategoryMatch> list = categoryMatchService.list(wrapper);
            if(CollectionUtils.isEmpty(list)){
                return null;
            }
            allTree = list.stream().map(e->{
                Category category = new Category();
                BeanUtils.copyProperties(e,category);
                category.setType(e.getType().getCode());
                return category;
            }).collect(Collectors.toList());
        }else {
            LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Category::getType, type);
            if(null != categoryIdList && categoryIdList.size() > 0){
                lambdaQueryWrapper.in(Category::getId, categoryIdList);
            }
            if(status >= 0){
                lambdaQueryWrapper.eq(Category::getStatus, status);
            }
            lambdaQueryWrapper.orderByDesc(Category::getSort);
            lambdaQueryWrapper.orderByAsc(Category::getId);
            allTree = dao.selectList(lambdaQueryWrapper);
        }
        if(allTree == null){
            return null;
        }
        for (Category category: allTree) {
            CategoryTreeVo categoryTreeVo = new CategoryTreeVo();
            BeanUtils.copyProperties(category, categoryTreeVo);
            treeList.add(categoryTreeVo);
        }
        //返回
        Map<Integer, CategoryTreeVo> map = new HashMap<>();
        //ID 为 key 存储到map 中
        for (CategoryTreeVo categoryTreeVo1 : treeList) {
            map.put(categoryTreeVo1.getId(), categoryTreeVo1);
        }
        List<CategoryTreeVo> list = new ArrayList<>();
        for (CategoryTreeVo tree : treeList) {
            //子集ID返回对象，有则添加。
            CategoryTreeVo tree1 = map.get(tree.getPid());
            if(tree1 != null){
                tree1.getChild().add(tree);
            }else {
                tree.setCids(tree.getId().toString());
                list.add(tree);
            }
        }
        //全部
        for (CategoryTreeVo tree : list) {
            //子集大于0，有则添加。
            List<CategoryTreeVo> childList = tree.getChild();
            StringBuilder  allBuilder = new StringBuilder();
            if (CollectionUtils.isNotEmpty(childList)) {
                for (CategoryTreeVo child : childList){
                    if (null != child.getId()) {
                        //全部
                        allBuilder.append(child.getId()).append(",");
                        //子类
                        child.setCids(child.getId().toString());
                        if(CollectionUtils.isNotEmpty(child.getChild())){
                            child.getChild().forEach(e->e.setCids(e.getId().toString()));
                        }
                    }
                }
                CategoryTreeVo all = new CategoryTreeVo();
                all.setCids(allBuilder.deleteCharAt(allBuilder.length() - 1).toString());
                all.setPid(tree.getPid());
                all.setType(1);
                all.setSort(1);
                all.setPath(tree.getPath() + tree.getId());
                all.setStatus(true);
                all.setName("全部" + tree.getName());
                //重新排序
                List<CategoryTreeVo> newChild = new ArrayList<>();
                newChild.add(all);
                newChild.addAll(childList);
                tree.setChild(newChild);
            }
        }
        return list;
    }

    /**
     * 删除分类表
     * @param id Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return bool
     */
    @Override
    public int delete(Integer id) {
        //查看是否有子类, 物理删除
        if(getChildCountByPid(id) > 0){
            throw new CrmebException("当前分类下有子类，请先删除子类！");
        }

        return dao.deleteById(id);
    }

    /**
     * 获取分类下子类
     * @param pid Integer
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return List<Category>
     */
    @Override
    public List<Category> getChildVoListByPid(Integer pid) {
        //查看是否有子类
        QueryWrapper<Category> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("status", 1);
        objectQueryWrapper.like("path", "/"+pid+"/");
        return dao.selectList(objectQueryWrapper);
    }

    /**
     * 检测分类名称是否存在
     * @param name String 分类名
     * @param type int 类型
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return int
     */
    @Override
    public int checkName(String name, Integer type) {
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Category::getName, name)
                .eq(Category::getType, type);
        return dao.selectCount(lambdaQueryWrapper);
    }

    /**
     * 检测url是否存在
     * @param uri String url
     * @author Mr.Zhang
     * @since 2020-04-16
     * @return int
     */
    @Override
    public boolean checkUrl(String uri) {
        // 拦截商户越权操作
        /* SystemAdmin systemAdmin = systemAdminService.getInfo();
        if(null == systemAdmin || StringUtils.isBlank(systemAdmin.getRoles())){
            throw new CrmebException("没有权限访问！");
        }
        if(null != systemAdmin.getMerId() && !uri.startsWith("api/admin/mer")) {
            throw new CrmebException("没有权限访问！");
        }*/
        
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Category::getUrl, uri);
        return dao.selectCount(lambdaQueryWrapper) > 0;
    }

    /**
     * 获取类目名称
     *
     * @param cateId
     */
    @Override
    public String getCategoryName(String cateId) {
        String categoryName = "";
        if (StringUtils.isNotBlank(cateId)){
           Category category = dao.selectById(cateId);
           if (ObjectUtils.isNotEmpty(category)){
               categoryName = category.getName();
           }
        }
        return categoryName;
    }

    public static void main(String[] args) {
        Set<Integer> set1 = new HashSet<>();
        set1.add(1);
        set1.add(2);

        Set<Integer> set2 = new HashSet<>();
        set2.add(2);
        set2.add(3);

        Set<Integer> set3 = new HashSet<>(set1);

        set1.retainAll(set2);

//        set1.removeAll(set2);
//
        System.out.println(set1);

        System.out.println(set3);

    }

    /**
     * 修改分类加价率
     * @param request
     * @param merId
     * @return
     */
    @Override
    public CommonResult<Object> updateCateRatio(UpdateCateRatioRequest request, Integer merId) {
        if(BigDecimal.ZERO.compareTo(request.getRatio())>0){
            throw new CrmebException("分类的加价率必须大于等于0");
        }
        if(request.getCateId()<0){
            throw new CrmebException("分类不能小于0");
        }
        //获取分类子类
        Set<Integer> cateIdSet = categoryMatchService.list(Wrappers.lambdaQuery(CategoryMatch.class).like(CategoryMatch::getPath, "/" + request.getCateId() + "/")).stream().map(CategoryMatch::getId).collect(Collectors.toSet());
        //cateId为0设置所有
        if(request.getCateId()!=0){
            cateIdSet.add(request.getCateId());
        }
        //商户分类
        Set<Integer> collect = channelCategoryConfigService.list(Wrappers.lambdaQuery(ChannelCategoryConfig.class).eq(ChannelCategoryConfig::getMerId, merId)).stream().map(ChannelCategoryConfig::getCateId).collect(Collectors.toSet());
        //添加
        Set<Integer> saveSet = new HashSet<>(cateIdSet);
        saveSet.removeAll(collect);
        if(CollectionUtils.isNotEmpty(saveSet)){
            List<ChannelCategoryConfig> saveList = saveSet.stream().map(e -> {
                ChannelCategoryConfig channelCategoryConfig = new ChannelCategoryConfig();
                channelCategoryConfig.setCreateTime(new Date()).setUpdateTime(new Date()).setMerId(merId).setRatio(request.getRatio()).setCateId(e);
                return channelCategoryConfig;
            }).collect(Collectors.toList());
            boolean b = channelCategoryConfigService.saveBatch(saveList);
            if(!b){
                throw new CrmebException("修改分类加价率异常1");
            }
        }
        //修改
        cateIdSet.retainAll(collect);
        if(CollectionUtils.isNotEmpty(cateIdSet)){
            boolean update = channelCategoryConfigService.update(Wrappers.lambdaUpdate(ChannelCategoryConfig.class).eq(ChannelCategoryConfig::getMerId, merId)
                    .in(ChannelCategoryConfig::getCateId, cateIdSet)
                    .set(ChannelCategoryConfig::getRatio, request.getRatio())
                    .set(ChannelCategoryConfig::getUpdateTime, new Date()));
            if(!update){
                throw new CrmebException("修改分类加价率异常2");
            }
        }
        return CommonResult.success();
    }

    /**
     * 获取商户分类
     * @param type
     * @param status
     * @param merId
     * @return
     */
    @Override
    public List<CategoryTreeVo> getMerListTree(Integer type, Integer status, Integer merId) {
        List<CategoryTreeVo> listTree = getListTree(type, status, (Integer) null);
        // 获取商户配置
        List<ChannelCategoryConfig> cateConfigs = channelCategoryConfigService.list(Wrappers.<ChannelCategoryConfig>lambdaQuery()
                .eq(ChannelCategoryConfig :: getMerId, merId)
        );
        Map<Integer, ChannelCategoryConfig> map = cateConfigs.stream().collect(Collectors.toMap(ChannelCategoryConfig::getCateId, e -> e));
        return filterNode(listTree,map);
    }

    @Override
    public List<Category> getMerCateList(CategorySearchRequest request, PageParamRequest pageParamRequest, Integer merId) {
        List<ChannelCategoryConfig> cateConfigs = channelCategoryConfigService.list(Wrappers.<ChannelCategoryConfig>lambdaQuery()
                .eq(ChannelCategoryConfig :: getMerId, merId)
        );
        Map<Integer, ChannelCategoryConfig> map = cateConfigs.stream().collect(Collectors.toMap(ChannelCategoryConfig::getCateId, e -> e));
        request.setType(1);
        request.setStatus(true);
        List<Category> categorys = getList(request, pageParamRequest);
        Set<Integer> cateIds = map.keySet();
        List<Category> tagCategory = new ArrayList<>();
        for(Category category : categorys) {
            if(!category.getStatus()){
                tagCategory.add(category);
                continue;
            }
            if(cateIds.contains(category.getId())){
                category.setIsAdvice(map.get(category.getId()).getIsAdvice() ? 1 : 0);
                category.setRatio(map.get(category.getId()).getRatio());
            }else {
                category.setIsAdvice(0);
            }
        }
        categorys.removeAll(tagCategory);
        return categorys;
    }

    /**
     * 递归处理商户分类结构
     * @param listTree
     * @param map
     * @return
     */
    private static List<CategoryTreeVo> filterNode(List<CategoryTreeVo> listTree, Map<Integer, ChannelCategoryConfig> map) {
        for (CategoryTreeVo treeVo : listTree) {
            if (Objects.nonNull(map.get(treeVo.getId()))) {
                treeVo.setIsAdvice(map.get(treeVo.getId()).getIsAdvice() ? 1 : 0);
                treeVo.setRatio(map.get(treeVo.getId()).getRatio());
                //设置商户自定义分类图片和开启状态
                if (StringUtils.isNotBlank(map.get(treeVo.getId()).getExtra())){
                    treeVo.setExtra(map.get(treeVo.getId()).getExtra());
                }
                treeVo.setStatus(treeVo.getStatus() ? map.get(treeVo.getId()).getStatus() : treeVo.getStatus());
            } else {
                treeVo.setIsAdvice(0);
            }
            //商户分类启用状态默认正常
            treeVo.setEnableFlag(Objects.nonNull(map.get(treeVo.getId())) ? map.get(treeVo.getId()).getEnableFlag() : true);
            if(treeVo.getChild()!= null && treeVo.getChild().size() > 0){
                filterNode(treeVo.getChild(), map);
            }
        }
        return listTree;
    }

    /**
     * 带权限的属性结构
     *
     * @param type
     * @param status
     * @param identityType
     * @return
     */
    @Override
    public List<CategoryTreeVo> getListTreeDetail(Integer type, Integer status, Integer identityType, Integer merId) {
        if (Objects.isNull(identityType) || Objects.isNull(IdentityTypeEnum.getEnumValue(identityType)) || Constants.CATEGORY_TYPE_MENU != type) {
            return getListTree(type, status, merId);
        }
        return getMenuTree(type, status, identityType);
    }

    /**
     * 菜单详情列表
     * @param type
     * @param status
     * @param identityType
     * @return
     */
    private List<CategoryTreeVo> getMenuTree(Integer type, Integer status, Integer identityType) {
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Category::getType, type);
        lambdaQueryWrapper.eq(status >= 0, Category::getStatus, status);
        lambdaQueryWrapper.orderByDesc(Category::getSort);
        lambdaQueryWrapper.orderByAsc(Category::getId);
        List<Category> allTree = dao.selectList(lambdaQueryWrapper);
        if (Objects.isNull(allTree)) {
            return null;
        }
        List<CategoryTreeVo> treeList = new ArrayList<>();

        Map<Integer, Set<Integer>> identityTypeMap = new HashMap<>();
        if (Constants.CATEGORY_TYPE_MENU == type) {
            List<Integer> ids = allTree.stream().map(Category::getId).collect(Collectors.toList());
            identityTypeMap = categoryMenuTypeService.getMenuIdentityTypeMap(identityType, ids);
        }

        for (Category category : allTree) {
            CategoryTreeVo categoryTreeVo = new CategoryTreeVo();
            BeanUtils.copyProperties(category, categoryTreeVo);
            categoryTreeVo.setIdentityTypes(identityTypeMap.get(category.getId()));
            if (CollectionUtils.isNotEmpty(categoryTreeVo.getIdentityTypes()) && categoryTreeVo.getIdentityTypes().contains(identityType)) {
                treeList.add(categoryTreeVo);
            }
        }

        //返回
        Map<Integer, CategoryTreeVo> map = new HashMap<>();
        //ID 为 key 存储到map 中
        for (CategoryTreeVo categoryTreeVo1 : treeList) {
            map.put(categoryTreeVo1.getId(), categoryTreeVo1);
        }

        List<CategoryTreeVo> list = new ArrayList<>();
        for (CategoryTreeVo tree : treeList) {
            //子集ID返回对象，有则添加。
            CategoryTreeVo tree1 = map.get(tree.getPid());
            if (tree1 != null) {
                tree1.getChild().add(tree);
            } else {
                list.add(tree);
            }
        }
        return list;
    }

    /**
     * 获取当前父级下所有菜单id
     * @param id
     * @return
     */
    @Override
    public List<Integer> getAllCateIds(Integer id) {
        Category category = this.getById(id);
        if (Objects.isNull(category)) {
            throw new CrmebException("当前菜单不存在");
        }
        if (category.getPid() == 0) {
            // 查询所有
            List<Category> list = this.list(Wrappers.<Category>lambdaQuery().like(Category::getPath, "/0/" + id));
            List<Integer> idList = list.stream().map(Category::getId).collect(Collectors.toList());
            idList.add(id);
            return idList;
        }
        return new ArrayList<>();
    }

    @Override
    public List<CategoryMatch> getMainCategoryList() {
        return categoryMatchService.list(Wrappers.<CategoryMatch>lambdaQuery().eq(CategoryMatch::getPid, 0));
    }
}

